<template>
    <div>
        <div v-if="!lastError.isError" class="box" v-loading="loadState">
            <directory-breadcrumb class="breadcrumb" :history-dir="historyDir" @jump-to="jumpTo"></directory-breadcrumb>
            <div class="table">
                <file-table
                        :try-load="loadPage"
                        :page-size="pageSize"
                        :title="title"
                        :table-data.sync="tableData"
                        @row-clicked="rowClicked"
                        ref="fileTable"
                >
                    <slot></slot>
                    <file-operator-column
                            @preview="$emit('preview',$event)"
                            @download-file="$emit('download-file',$event)"
                            @open-dir="openDir"
                            @change-file-meta="$emit('change-file-meta',$event)"
                            @delete="$emit('delete',$event)"
                            :enableChangeFileMeta="enableChangeFileMeta"
                            :enable-delete="enableDelete"
                    ></file-operator-column>
                </file-table>
            </div>
            <table-pagination
                    :page-size="pageSize"
                    :current-page.sync="currentPage"
                    :length="currentDir.length"
                    class="pagination">
            </table-pagination>
        </div>
        <table-error v-else :title="title" :error-message="lastError.errorMessage" @handle-error="loadRoot"></table-error>
    </div>
</template>

<script>
    import DirectoryBreadcrumb from "~/components/file-list/base-file-list/DirectoryBreadcrumb";
    import FileTable from "~/components/file-list/base-file-list/FileTable";
    import TablePagination from "~/components/file-list/base-file-list/TablePagination";
    import FileOperatorColumn from "~/components/file-list/table-columns/FileOperatorColumn";
    import TableError from "~/components/file-list/base-file-list/TableError";
    /**
     * 最基本的文件列表，只包含文件列表和分页
     * 只会缓存当前显示出的列表信息和分页信息。
     * 会记住文件夹的页码，当跳出某文件夹再返回，会回到上次的页码。
     *
     * 这个组件本质上为 <id,page> 的二元组，并保存了<id,page>指向的文件元信息列表。
     * 这个组件会通过当前<id,page>的文件元信息列表和历史文件目录主动地切换id和page。
     */
    export default {
        name: "BaseFileList",
        components: {TableError, FileOperatorColumn, TablePagination, DirectoryBreadcrumb,FileTable},
        props:{
            enableChangeFileMeta:{
                type: Boolean,
                default: true
            },
            enableDelete:{
                type: Boolean,
                default: true
            },
            pageSize:{
                type: Number,
                default: 12,
            },
            /**
             * 加载某文件夹的某页文件 <br>
             *     为以下形式的异步函数 async loadPage({id,page},pageSize)。
             *     函数将会被自动调用，并传入 dirId：文件夹元信息id、page：页码（从1开始）、pageSize：单页大小。
             */
            loadPage:{
                type: Function,
                required:true
            },
            /**
             *  加载根路径元数据 <br>
             *      为以下形式的异步函数 async loadRoot()。
             *      函数将会被自动调用。
             */
            loadRootMeta:{
                type:Function,
                required: true
            },
            title:{
                type:String,
                default: "",
            },
            currentDir:{
                type: Object,
                require: true,
            },
        },
        data(){
            return{
                historyDir:[],
                lightHistoryMode: false,
                tableData:[],
                pageHistory:{},
                loadState: true,
                lastError: {
                    isError: false,
                    errorMessage: "",
                },
                currentPage:1,
            };
        },
        methods:{
            jumpTo(dir){
                if(dir.id===this.currentDir.id)return undefined;
                let i=this.historyDir.length-1;
                while(i>=0&&this.historyDir[i].id!==dir.id)i--;
                this.historyDir = this.historyDir.slice(0,i+1);
                this.checkoutDir(this.historyDir[i]);
                this.lightHistoryMode = false;
            },
            // 当light==true时,此history将会被以后的任意一级文件夹替换。
            openDir(dir,light){
                if(dir.id===this.currentDir.id&&dir.id>0)return undefined;
                light = Boolean(light);
                if(dir.id <= 0 || !this.historyDir.some(d => d.id === dir.id)) {
                    if(this.lightHistoryMode){
                        this.historyDir.pop();
                        this.lightHistoryMode = false;
                    }
                    this.historyDir.push(dir);
                    this.lightHistoryMode = light;
                }
                this.checkoutDir(dir);
            },
            checkoutDir(dir){
                console.log("打开文件夹 ",dir);
                this.$emit("update:currentDir",dir);
                if(!this.pageHistory[dir.id]){
                    this.pageHistory[dir.id] = 1;
                }
                this.currentPage = this.pageHistory[dir.id];
                this.$refs.fileTable.$emit("data-update",{id:dir.id,page:this.pageHistory[dir.id]},this.pageSize);
            },
            async loadRoot(){
                this.loadState = true;
                this.clearError();
                try {
                    const loadAns = await this.loadRootMeta();
                    this.openDir(loadAns);
                }catch (e) {
                    this.createMetaError(e.message);
                } finally {
                    this.loadState = false;
                }
            },
            createMetaError(msg){
                if(typeof msg==="string"){
                    this.lastError.errorMessage = msg;
                }
                this.lastError.isError = true;
            },
            clearError(){
                this.lastError.errorMessage = "";
                this.lastError.isError = false;
            },
            rowClicked(file,col){
                if(col.label==="操作")return undefined;
                if(file&&file.isDir){
                    this.openDir(file);
                }else{
                    this.$emit('preview',file);
                }
            },
        },
        watch:{
            currentPage(newValue){
                this.pageHistory[this.currentDir.id] = newValue;
                this.$refs.fileTable.$emit("data-update",{id:this.currentDir.id,page:newValue},this.pageSize);
            }
        },
        mounted() {
            this.loadRoot();
            this.$on("open-dir", this.openDir);
            this.$on("reload",()=>{
                this.$refs.fileTable.$emit("data-update",{id:this.currentDir.id,page:this.currentPage},this.pageSize)
            });
        }
    }
</script>

<style scoped>
    .box{
        height: 100%;
        width: 100%;
        position: relative;
    }
    .table{
        height: 71vh;
    }
</style>